﻿using CodeMonkey.EditableObject.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CodeMonkey.EditableObject.Descriptor
{
    //from http://msdn.microsoft.com/en-us/library/system.componentmodel.propertydescriptor(v=vs.110).aspx
    //PropertyDescriptor :  Provides an abstraction of a property on a class.
    // A description of a property consists of a name, its attributes, the component class that the property is associated with, and the type of the property.
    /// <summary>
    /// 可回滚属性;也就是Model中的哪些属性;这里是Contact
    /// </summary>
    public class TransacablePropertyDescriptor : PropertyDescriptor
    {
        private PropertyInfo underneathPropInfo;
        private bool isReadOnly;
        /// <summary>
        /// 指示该PropertyDescriptor描述的数据类型是否为数值类型
        /// </summary>
        private bool isDigitType;

        public TransacablePropertyDescriptor(PropertyInfo property) :
            base(property.Name, null)
        {
            if (property == null)
            {
                throw new ArgumentNullException("property");
            }

            underneathPropInfo = property;
            isReadOnly = property.GetSetMethod() == null;
            isDigitType = property.PropertyType.IsValueType && property.PropertyType.IsPrimitive && !property.PropertyType.IsEnum; //这里用IsPrimitive剔除其它;指示该PropertyDescriptor描述的数据类型是否为数值类型
        }

        public override bool CanResetValue(object component)
        {
            return false;
        }

        public override Type ComponentType
        {
            get { return underneathPropInfo.DeclaringType; }
        }

        public override bool IsReadOnly
        {
            get { return isReadOnly; }
        }

        public override Type PropertyType
        {
            get { return isDigitType ? typeof(string) : this.underneathPropInfo.PropertyType; }
        }

        public override void ResetValue(object component)
        {
        }

        public override object GetValue(object component) //这里参数component,就是继承自EditableModelBase<T>的子类
        {
            var transacable = component as ITransacableObject;
            if (transacable == null)
            {
                return underneathPropInfo.GetValue(component, null);
            }
            else
            {
                return isDigitType ? transacable.ReadPropertyValue(underneathPropInfo).ToString() :
                                                        transacable.ReadPropertyValue(this.underneathPropInfo);
            }
        }

        public override void SetValue(object component, object value)
        {
            var transacable = component as ITransacableObject;
            if (transacable == null)
            {
                underneathPropInfo.SetValue(component, value, null);
            }
            else
            {
                transacable.SetPropertyValue(underneathPropInfo, value);
            }
        }

        public override bool ShouldSerializeValue(object component)
        {
            // 先简单起见
            return false;
        }
    }
}
